package cn.vehicle.biz.core.support.abs;

import cn.vehicle.biz.core.support.PlateDetectSupport;
import cn.vehicle.constants.Constants;
import cn.vehicle.domains.ctx.PlateDetectContext;
import cn.vehicle.domains.entity.CameraEntity;
import cn.vehicle.domains.entity.CommonVehicleEntity;
import cn.vehicle.domains.entity.VehicleCommonLedgerEntity;
import cn.vehicle.exception.VehicleAccessException;
import cn.vehicle.service.VehicleCommonLedgerService;
import cn.vehicle.utils.Base64ToImageUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

/**
 * 车辆识别抽象支持类
 * <p>
 * 提供车牌识别的通用处理逻辑，包括进场校验、进出记录的通用实现。
 * 各具体车辆类型（如运输车辆、厂内车辆等）可继承该类并实现自定义逻辑。
 * </p>
 *
 * <p>主要职责：</p>
 * <ul>
 *   <li>校验车辆合法性（是否启用、是否过期等）；</li>
 *   <li>记录车辆进出场台账信息；</li>
 *   <li>保存车牌和车辆图片，关联摄像头信息；</li>
 *   <li>提供基础支撑逻辑供子类复用。</li>
 * </ul>
 */
@Slf4j
public abstract class AbstractSupport implements PlateDetectSupport {

    @Resource
    private VehicleCommonLedgerService vehicleCommonLedgerService;

    @Override
    public void processIn(PlateDetectContext plateDetectContext) {
        CommonVehicleEntity commonVehicleEntity = plateDetectContext.getCommonVehicleEntity();

        if (commonVehicleEntity == null) {
            throw VehicleAccessException.SYSTEM_ERROR.newInstance("车辆未录入");
        }

        if (!commonVehicleEntity.getEnabled()) {
            throw VehicleAccessException.SYSTEM_ERROR.newInstance("车辆已失效");
        }

        if (commonVehicleEntity.getExpireTime().getTime() < System.currentTimeMillis()) {
            throw VehicleAccessException.SYSTEM_ERROR.newInstance("车辆已过期");
        }
    }

    @Override
    public void recordIn(PlateDetectContext plateDetectContext) {
        VehicleCommonLedgerEntity vehicleCommonLedgerEntity = new VehicleCommonLedgerEntity();


        vehicleCommonLedgerEntity.setVehicleNumber(plateDetectContext.getVehicleNumber());
        vehicleCommonLedgerEntity.setVehicleType(plateDetectContext.getVehicleType());
        vehicleCommonLedgerEntity.setEntryTime(new Date());
        vehicleCommonLedgerEntity.setEntryOperator(Constants.SYSTEM_OPERATOR);

        //存的是这个照片在电脑里面的路径
        vehicleCommonLedgerEntity.setEntryVehicleImgUrl(Base64ToImageUtil.saveBase64(plateDetectContext.getInternalVehicleInfo().getVehicleImgBase64(), null));
        vehicleCommonLedgerEntity.setEntryPlateImgUrl(Base64ToImageUtil.saveBase64(plateDetectContext.getInternalVehicleInfo().getPlateImgBase64(), null));

        CameraEntity cameraEntity = plateDetectContext.getCameraEntity();
        vehicleCommonLedgerEntity.setEntryCameraIp(cameraEntity.getCameraIp());
        vehicleCommonLedgerEntity.setEntryRoadCode(cameraEntity.getRoadCode());
        vehicleCommonLedgerEntity.setEntryExitCode(cameraEntity.getEntryExitCode());

        vehicleCommonLedgerService.insert(vehicleCommonLedgerEntity);

        plateDetectContext.setVehicleCommonLedgerEntity(vehicleCommonLedgerEntity);
    }


    /**
     * 记录车辆出场信息
     * <p>
     * 根据车辆最近一条进场记录生成或更新台账信息。
     * 若无进场记录或最近记录已出场，则新增一条出场记录；
     * 否则更新原有记录的出场信息。
     * </p>
     *
     * @param plateDetectContext 车辆识别上下文对象，包含车辆信息、相机信息、识别图片等
     */
    @Override
    public void recordOut(PlateDetectContext plateDetectContext) {
        // 获取该车牌号最近一次的台账记录（用于判断是否需要更新或新建）
        VehicleCommonLedgerEntity lastLedgerEntity = vehicleCommonLedgerService.getLastLedgerByVehicleNumber(plateDetectContext.getVehicleNumber());

        // 创建新的台账实体对象并填充基础信息
        VehicleCommonLedgerEntity vehicleCommonLedgerEntity = new VehicleCommonLedgerEntity();
        vehicleCommonLedgerEntity.setVehicleNumber(plateDetectContext.getVehicleNumber());
        vehicleCommonLedgerEntity.setVehicleType(plateDetectContext.getVehicleType());
        // 设置出场时间与操作人信息
        vehicleCommonLedgerEntity.setExitTime(new Date());
        vehicleCommonLedgerEntity.setExitOperator(Constants.SYSTEM_OPERATOR);

        // 保存出场车辆图片与车牌图片至本地，存储路径写入数据库
        vehicleCommonLedgerEntity.setExitVehicleImgUrl(Base64ToImageUtil.saveBase64(plateDetectContext.getInternalVehicleInfo().getVehicleImgBase64(), null));
        vehicleCommonLedgerEntity.setExitPlateImgUrl(Base64ToImageUtil.saveBase64(plateDetectContext.getInternalVehicleInfo().getPlateImgBase64(), null));

        // 获取当前识别事件对应的摄像头信息（包含IP、道路、进出口编码等）
        CameraEntity cameraEntity = plateDetectContext.getCameraEntity();
        vehicleCommonLedgerEntity.setExitCameraIp(cameraEntity.getCameraIp());
        vehicleCommonLedgerEntity.setExitRoadCode(cameraEntity.getRoadCode());
        vehicleCommonLedgerEntity.setExitEntryExitCode(cameraEntity.getEntryExitCode());

        // 若不存在进场记录或最近记录已出场，则新增新的出场记录
        if (lastLedgerEntity == null || lastLedgerEntity.getExitTime() != null) {
            vehicleCommonLedgerService.insert(vehicleCommonLedgerEntity);
        } else {
            // 若存在未出场的进场记录，则更新该记录的出场信息
            vehicleCommonLedgerEntity.setId(lastLedgerEntity.getId());
            vehicleCommonLedgerService.updateVehicleExitInfo(vehicleCommonLedgerEntity);
            vehicleCommonLedgerEntity.setAssociationId(lastLedgerEntity.getAssociationId());
        }

        // 将出场台账实体保存到上下文中，供后续流程使用
        plateDetectContext.setVehicleCommonLedgerEntity(vehicleCommonLedgerEntity);
    }
}
